﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using WorkFlowCore.IRepositories;

namespace WorkFlowCore.FormDesigns
{
    public class FormDesignManager: IDomainService
    {
        private readonly IFormDesignInfoRepository formDesignRepository;
        private readonly IBasicRepository<FormDesignVersion> formDesignVersionRepository;

        public FormDesignManager(IFormDesignInfoRepository formDesignRepository, IBasicRepository<FormDesignVersion> formDesignVersionRepository)
        {
            this.formDesignRepository = formDesignRepository;
            this.formDesignVersionRepository = formDesignVersionRepository;
        }

        public async Task<FormDesign> CreateFormDesign(string formType, string title, string description, WorkflowId4FormDesign workflowId)
        {
            var formDesignInfo = await formDesignRepository.GetAsync(f => f.WorkflowId_Id == workflowId.Id && f.WorkflowId_Version == workflowId.Version);
            if (formDesignInfo != null)
            {
                throw new Exception("一个流程版本只能有一个表单设计，考虑在现有设计基础增加版本");
            }

            FormDesign formDesign = new FormDesign(formType, title, description,workflowId);


            await formDesignRepository.InsertAsync(formDesign.ToFormDesignInfo());
            return formDesign;
        }

        public async Task<FormDesignVersion> UpdateFormDesignVersion(FormDesignId formDesignId, string formType, string title, string description, string designContent, WorkflowId4FormDesign workflowId,string designFramework)
        {
            FormDesignInfo formDesignInfo = await formDesignRepository.GetAsync(f => f.Id == formDesignId.Id);
            FormDesign formDesign = formDesignInfo.ToFormDesign();
            formDesign.Update(formType, title, description,workflowId);
            formDesign.SetActiveVersionIfEmpty(formDesignId.Version);

            await formDesignRepository.UpdateAsync(formDesign.ToFormDesignInfo(formDesignInfo));
            var formDesignVersion = await formDesignVersionRepository.GetAsync(f => f.FormDesignId == formDesignId.Id && f.Version == formDesignId.Version);

            if (formDesignVersion == null)
            {
                formDesignVersion = new FormDesignVersion(formDesignId.Id, formDesignId.Version, designContent, designFramework);
                return await formDesignVersionRepository.InsertAsync(formDesignVersion);
            }
            else
            {
                formDesignVersion.Update(designContent,designFramework);
                return await formDesignVersionRepository.UpdateAsync(formDesignVersion);
            }
        }


        public async Task<FormDesignVersion> AddOrUpdateFormDesignVersion(WorkflowId4FormDesign workflowId,int designVersion, string formType, string title, string description, string designContent, string designFramework)
        {
            FormDesignInfo formDesignInfo = await formDesignRepository.GetAsync(f => f.WorkflowId_Id == workflowId.Id && f.WorkflowId_Version == workflowId.Version);
            FormDesign formDesign = null;
            FormDesignId formDesignId = null;
            if (formDesignInfo == null)
            {
                formDesign = new FormDesign(formType, title, description, workflowId);
                formDesignInfo = formDesign.ToFormDesignInfo();
                await formDesignRepository.InsertAsync(formDesignInfo);
                formDesignId = new FormDesignId(formDesign.Id, designVersion);
            }
            else {

                formDesign = formDesignInfo.ToFormDesign();
                formDesign.Update(formType, title, description, workflowId);
                formDesignId = new FormDesignId(formDesign.Id, designVersion);
                formDesign.SetActiveVersionIfEmpty(formDesignId.Version);

                await formDesignRepository.UpdateAsync(formDesign.ToFormDesignInfo(formDesignInfo));
            }
                        
            var formDesignVersion = await formDesignVersionRepository.GetAsync(f => f.FormDesignId == formDesignId.Id && f.Version == formDesignId.Version);

            if (formDesignVersion == null)
            {
                formDesignVersion = new FormDesignVersion(formDesignId.Id, formDesignId.Version, designContent, designFramework);
                return await formDesignVersionRepository.InsertAsync(formDesignVersion);
            }
            else
            {
                formDesignVersion.Update(designContent, designFramework);
                return await formDesignVersionRepository.UpdateAsync(formDesignVersion);
            }
        }

        public async Task<FormDesignVersion> GetFormDesignVersion(FormDesignId formDesignId)
        {
            return await formDesignVersionRepository.GetAsync(f => f.FormDesignId == formDesignId.Id && f.Version == formDesignId.Version);
        }

        public async Task<FormDesignVersion> GetFormDesignActiveVersion(WorkflowId4FormDesign workflowId)
        {
            var formDesign = await formDesignRepository.GetAsync(f=>f.WorkflowId_Id==workflowId.Id && f.WorkflowId_Version==workflowId.Version);
            if (formDesign == null) return null;

            return await formDesignVersionRepository.GetAsync(f => f.FormDesignId == formDesign.Id && f.Version == formDesign.ActiveVersion);
        }

        public async Task DeleteFormDesign(Guid formDesignId)
        {
            FormDesignInfo formDesignInfo = await formDesignRepository.GetAsync(f => f.Id == formDesignId);
            FormDesign formDesign = formDesignInfo.ToFormDesign();
            await formDesignRepository.DeleteAsync(formDesign.ToFormDesignInfo(formDesignInfo));
            var formDesignVersions = await formDesignVersionRepository.GetListAsync(f => f.FormDesignId == formDesignId);
            foreach (var formDesignVersion in formDesignVersions)
            {
                formDesignVersion.Delete();
                await formDesignVersionRepository.UpdateAsync(formDesignVersion);
            }
        }

        public async Task<List<FormDesign>> GetAllFormDesignVersions(Guid formDesignId)
        {
            var formDesignVersions = await formDesignVersionRepository.GetListAsync(f => f.FormDesignId == formDesignId && !f.Deleted);
            var formDesignInfo = await formDesignRepository.GetAsync(f => f.Id == formDesignId && !f.Deleted);
            var formDesign = formDesignInfo.ToFormDesign();
            if (formDesign == null) return new List<FormDesign>();
            return formDesignVersions.Select(f =>
            {
                var fd = new FormDesign(formDesign.FormType, formDesign.Title, formDesign.Description,formDesign.WorkflowId);
                fd.SetActiveVersion(f.Version);
                fd.Id = formDesign.Id;
                return fd;
            }).ToList();
        }

        public async Task<List<SimpleFormDesignVersion>> GetAllFormDesignVersionsByWorkflowId(WorkflowId4FormDesign workflowId)
        {
            FormDesignInfo formDesignInfo = await formDesignRepository.GetAsync(f =>f.Deleted==false && f.WorkflowId_Id == workflowId.Id && f.WorkflowId_Version == workflowId.Version);

            if(formDesignInfo == null)
            {
                return new List<SimpleFormDesignVersion>();
            }
            
            var formDesignVersions = await formDesignVersionRepository.GetListAsync(f => f.FormDesignId == formDesignInfo.Id && !f.Deleted);
            var formDesign = formDesignInfo.ToFormDesign();
            if (formDesign == null) return new List<SimpleFormDesignVersion>();
            return formDesignVersions.Select(f =>new SimpleFormDesignVersion
            {
                FormDesignId = formDesignInfo.Id,
                ActiveVersion = formDesign.ActiveVersion,
                Description = formDesign.Description,
                FormType = formDesign.FormType,
                Title = formDesign.Title,
                Version = f.Version,
            }).ToList();
        }
        /// <summary>
        /// 设置激活版本
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task SetActiveVersion(FormDesignId id)
        {
            FormDesignInfo formDesignInfo = await formDesignRepository.GetAsync(f => f.Id == id.Id);
            FormDesign formDesign = formDesignInfo.ToFormDesign();
            formDesign.SetActiveVersion(id.Version);
            await formDesignRepository.UpdateAsync(formDesign.ToFormDesignInfo(formDesignInfo));
        }

        /// <summary>
        /// 根据流程设计获取表单设计
        /// </summary>
        /// <param name="workflowIds"></param>
        /// <returns></returns>
        public async Task<List<FormDesign>> GetFormDesignsOfWorkflowId(WorkflowId4FormDesign[] workflowIds)
        {
            var formDesigns = await formDesignRepository.GetFormDesignsOfWorkflowId(workflowIds);
            return formDesigns;
        }

    }
}
